#pragma once

struct IFile
{
    virtual ~IFile() { }

    virtual void display() = 0;
    virtual bool add(IFile* lpIFile) = 0;
    virtual bool remove(IFile* lpIFile) = 0;
    virtual std::list<IFile*>* GetChild() = 0;
};

class CFile : public IFile  //  leaf
{
private:
    std::string m_strName;

public:
    CFile(std::string strName) : m_strName(strName) { }
    virtual ~CFile() { }

public:
    virtual void display()
    {
        std::cout << m_strName << std::endl;
    }

    virtual bool add(IFile* lpIFile)
    {
        return false;
    }

    virtual bool remove(IFile* lpIFile)
    {
        return false;
    }

    virtual std::list<IFile*>* GetChild()
    {
        return nullptr;
    }
};

class CDirectory : public IFile //  composite
{
private:
    std::string m_strName;
    std::list<IFile*> m_FileList;

public:
    CDirectory(std::string name) :m_strName(name) { }
    virtual ~CDirectory() { }

public:
    virtual void display()
    {
        std::cout << m_strName << std::endl;
    }

    virtual bool add(IFile* lpIFile)
    {
        m_FileList.push_back(lpIFile);
        return 0;
    }

    virtual bool remove(IFile* lpIFile)
    {
        m_FileList.remove(lpIFile);
        return 0;
    }

    virtual std::list<IFile*>* GetChild()
    {
        return &m_FileList;
    }
};

void ShowTree(IFile* lpRoot, unsigned int level)
{
    if (!lpRoot) return;

    unsigned int i = 0;

    lpRoot->display();

    std::list<IFile*>* lpFileList = lpRoot->GetChild();

    if (lpFileList)
    {
        for (std::list<IFile*>::iterator it = lpFileList->begin(); it != lpFileList->end(); ++it)
        {
            if (!(*it)->GetChild())
            {
                for (i = 0; i < level; i++)
                {
                    std::cout << "  ";
                }
                std::cout << "-";
                (*it)->display();
            }
            else
            {
                static bool bFirst = false;
                if (!bFirst)
                {
                    std::cout << "  ";
                    bFirst = true;
                }

                for (i = 0; i < level; i++)
                {
                    std::cout << "  ";
                }

                ShowTree(*it, level + 1);
            }
        }
    }
}